package se.lth.student.axisandroidcam.server;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Calendar;
import java.util.GregorianCalendar;
import se.lth.student.axisandroidcam.client.Toolbox;

public class ServerOut extends Thread {
	private CameraThread cameraThread;
	private byte[] image;
	private byte[] imageToSend;
	private int imageLength;
	private boolean movieOn, movieOnAuto, hasMotion, forced;
	private ServerSocket socket;
	private Socket clientSocket;

	public ServerOut(CameraThread cameraThread) {
		this.cameraThread = cameraThread;
		forced = false;
		movieOn = false;
		movieOnAuto = false;
	}

	public void run() {
		while (true) {
			Toolbox.printDebug("Network started");
			try {
				clientSocket = socket.accept();
				forced = false;
				movieOn = false;
				movieOnAuto = false;
				Toolbox.printDebug("Connection established");
				OutputStream out = clientSocket.getOutputStream();
				DataOutputStream dos = new DataOutputStream(out);

				while (true) {
					Calendar c = new GregorianCalendar();
					long time = c.getTimeInMillis();
					image = cameraThread.getImage();
					imageLength = cameraThread.getImageLength();
					
					
					imageToSend = new byte[imageLength];
					System.arraycopy(image, 0, imageToSend, 0, imageLength);
					dos.writeInt(imageLength);
					if(!forced){
						hasMotion = cameraThread.hasMotion();
						setMovie(hasMotion);
						dos.writeBoolean(movieOnAuto);
					}else{						
						dos.writeBoolean(movieOn);
					}
					
				
					if (imageLength > 0) {
						dos.write(imageToSend, 0, imageLength);
						Toolbox.printDebug("Wrote image with size: "
								+ imageLength);
					}

					c = new GregorianCalendar();
					long a = c.getTimeInMillis() - time;
					
					
					if(!forced){
						if (movieOnAuto) {
							if (a > Server.MOVIE_PERIOD)
								a = 0;
							Thread.sleep(Server.MOVIE_PERIOD - a);
						} else {
							if (a > Server.IDLE_PERIOD)
								a = 0;
							Thread.sleep(Server.IDLE_PERIOD - a);
						}
					}else{
						if (movieOn) {
							if (a > Server.MOVIE_PERIOD)
								a = 0;
							Thread.sleep(Server.MOVIE_PERIOD - a);
						} else {
							if (a > Server.IDLE_PERIOD)
								a = 0;
							Thread.sleep(Server.IDLE_PERIOD - a);
						}
					}
					
					
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public synchronized boolean connect() {
		try {
			socket = new ServerSocket(Server.PORT + (Server.CAMERA_ID * 10));
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			Toolbox.printDebug("Socket failed to listen to port: "
					+ (Server.PORT + Server.CAMERA_ID));
			System.exit(-1);
			return false;
		}
	}

	public synchronized void setMovie(boolean movie) {
		if(movie != movieOnAuto){
			movieOnAuto = movie;
			Toolbox.printDebug("Movie set to: " + movie);
		}
	}
	
	public synchronized void forceMovie(boolean movie){
		movieOn = movie;
		forced = true;
	}

}
